/***********************************************************************************
 * 文件名： polsys.c
 * 版本： 3
 * 说明：
 * 		polsys 核心实现。 
 *      【polsys】
 *      使用软定时器原理的“多任务”系统, 轮询调用入口函数，非RTOS。支持在任意地方创建任务。
 *      【polsys_lite】
 *      通过在用户端提供宏定义配置的方式让用户添加几个固定间隔时间需要执行的任务函数，然后在
 *  Polsys_Loop 定时调用他们。 这样的机制可以在不支持函数指针的“低端RISC 8位单片机”中帮助代
 *  码去耦，让软件更具模块化和面向对象。
 *      【通用说明】
 *      polsys_port.c 文件中已经编写好移植示例，详见该文件内的注释说明。
 * 修改记录：
 * 	2021/04/28: 初版。 刘言。
 *  2021/05/19：合并polsys_lite。刘言。
 *  2021/11/15: 
 * 		定义 _POLSYS_DEBUG 后可以查看CPU使用率、是否过载等调试信息，每个TICK周期更新，过载
 * 	表示在一个TICK周期内不能执行完所有任务，一旦置位复位才能清除。
 * 		优化任务调度，现在只在有任务状态被标记为 TS_READY 后才会去扫描任务列表寻找并执行需要
 * 	执行的任务，其它时间都循环在执行 SYS_IDLE() 。刘言。
***********************************************************************************/
#include "polsys.h"

#ifdef POLSYS_LITE

bit _Polsys_mTicked = false;

#ifdef _POLSYS_TASK_GROUP_1000TICK
u8 _Polsys_TickCount = 0;
u8 _Polsys_10TickCount = 0;
u8 _Polsys_100TickCount = 0;
#elif (defined _POLSYS_TASK_GROUP_100TICK)
u8 _Polsys_TickCount = 0;
u8 _Polsys_10TickCount = 0;
#elif (defined _POLSYS_TASK_GROUP_10TICK)
u8 _Polsys_TickCount = 0;
#endif

#else
//自定义数据类型

typedef struct _sys_info
{
	polsys_task_t *Tasks[MAX_TASKS]; //所有的任务列表
#ifdef _POLSYS_DEBUG
	u8 NowRunTaskNo;			    //现在正在运行的任务号
	u8 CpuUsageLastTick;					// CPU使用率
	bool Overload;					// 过载，在一个TICK周期内不能执行完所有任务，复位才能清除。
	bool Ticked;					// 标记：Tick中断已经发生
#endif
	u8 TotalTask;				    //已添加的任务数量
	bool Busy;						// 标记：有任务需要执行。用于判断是否需要重新扫描一遍需要执行的任务并执行。
} sys_info_t;

static idata volatile sys_info_t mSysInfo;

void Polsys_Tick() //定时器中断调用 系统节拍 间隔 POLSYS_TICK_CYCLE ms
{
	u8 i;
	polsys_task_t *cTask;

	for (i = 0; i < mSysInfo.TotalTask; i++)
	{
		cTask = mSysInfo.Tasks[i];

		if (cTask->WaitTime > 0)
			cTask->WaitTime--;
		if (cTask->WaitTime == 0)
		{
			cTask->Status = TS_READY;
			cTask->WaitTime = cTask->Interval;
			mSysInfo.Busy = true;
		}
	}
#ifdef _POLSYS_DEBUG
	mSysInfo.Ticked = true;
#endif
}

void Polsys_Loop() //系统循环，用于执行任务，始终循环调用
{
	u8 i;
	polsys_task_t *cTask;

	mSysInfo.Busy = false;
	for (i = 0; i < mSysInfo.TotalTask; i++)
	{
		cTask = mSysInfo.Tasks[i];

		if (cTask->Status == TS_READY)
		{
#ifdef _POLSYS_DEBUG
			cTask->Status = TS_RUNNING;
			mSysInfo.NowRunTaskNo = i;
#endif
			cTask->EntryFunc();
			if (cTask->Interval > 0)
			{
				cTask->Status = TS_WAIT; // 标记为等待状态
			}
			else						// 没有间隔时间的任务不标记，始终READY
			{
#ifdef _POLSYS_DEBUG
				cTask->Status = TS_READY;
#endif
				mSysInfo.Busy = true;
			}
#ifdef _POLSYS_DEBUG
			mSysInfo.NowRunTaskNo = 255;
#endif
		}
	}
	//READY的任务执行完毕了，如果没有Interval=0的任务，进入空闲任务
#ifdef _POLSYS_DEBUG
	if(mSysInfo.Busy)
	{
		mSysInfo.CpuUsageLastTick = 100;
		mSysInfo.Overload = true;
	}
	else
#endif
	{
		while (!mSysInfo.Busy)		// 没有任务需要执行之前一直执行IDLE
		{
#ifdef _POLSYS_DEBUG
			if(mSysInfo.Ticked)
			{
				if(mSysInfo.Busy)break;
				mSysInfo.CpuUsageLastTick = _Polsys_GetTickTimerNowValue() * 100 / _Polsys_GetTickTimerCycleValue();
				mSysInfo.Ticked = false;
			}
#endif
			SYS_IDLE();
		}
	}
}

void Polsys_Init()
{
	_Polsys_ClockInit();	//系统时钟初始化
#ifdef _POLSYS_DEBUG
	mSysInfo.NowRunTaskNo = 255;
	mSysInfo.Overload = false;
#endif
	mSysInfo.TotalTask = 0;
	_Polsys_TickStart();
	Polsys_EnableInt();
}

bool Polsys_TaskInit(polsys_task_t *task_ptr, void (*Entry)(void), u16 Interval)
{
	if (mSysInfo.TotalTask >= MAX_TASKS)
		return false;

	// task 属性
	task_ptr->EntryFunc = Entry;
	task_ptr->Interval = Interval;
	task_ptr->WaitTime = Interval;
	task_ptr->Status = TS_WAIT;

	//添加到 task 列表
	mSysInfo.Tasks[mSysInfo.TotalTask] = task_ptr;

	mSysInfo.TotalTask++;

	return true;
}

#endif

